#ifndef __WILDARRAY_H__
#define __WILDARRAY_H__
#pragma once

//////////////////////////////////////////////////////////////////////////
// creator: Chinhungu
// useage: To Manager ID and string key ,and It stored data point.
//////////////////////////////////////////////////////////////////////////

#include <map>
#include <queue>
#include <string>

#define IWA_NULL (-1)
#define DEF_ARRAY_SIZE 2048

namespace wild
{

typedef std::string KeyString;

template<typename OB>
class WildArray
{
	typedef struct tagWideObjectNode
	{
		char active;
		OB* o;
	}WIDE_OBJECT_NODE;
	typedef std::map<KeyString,int> WOBJECT_LIST;
	typedef std::pair<KeyString,int> WOBJECT_PAIR;
public:
	WildArray(int size=DEF_ARRAY_SIZE) : _iNowPtr(0),_object(NULL)
	{
		_object = new WIDE_OBJECT_NODE[size];
		_iMaxSize = size;
		_iSize = 0;
		_iNowPtr = 0;
		memset(_object,0,sizeof(WIDE_OBJECT_NODE)*_iMaxSize);

		for(int i=0;i<_iMaxSize;i++)
			_oFreeList.push(i);
	}
	virtual ~WildArray()
	{
		if(_object)
		{
			delete[] _object;
			_object = NULL;
		}

		while(!_oFreeList.empty())
			_oFreeList.pop();

		_iSize = 0;
	}

	void Reserve(size_t size)
	{
		if(_object)
		{
			delete[] _object;
			_object = NULL;
		}

		while(!_oFreeList.empty())
			_oFreeList.pop();

		_object = new WIDE_OBJECT_NODE[size];
		_iMaxSize = (int)size;

		memset(_object,0,sizeof(WIDE_OBJECT_NODE)*_iMaxSize);

		for(int i=0;i<_iMaxSize;i++)
			_oFreeList.push(i);

		_iSize = 0;
		_iNowPtr = 0;
	}

	int	Add(OB *o)
	{
		WIDE_OBJECT_NODE *n = _object;

		if(_oFreeList.empty())
			return IWA_NULL;


		int i = _oFreeList.front();

		if(i>=0&&i<_iMaxSize)
		{

			if (!_object[i].active)
			{
				_object[i].active = true;

				_object[i].o = o;
				_iSize++;		
				_oFreeList.pop();


				return (i);
			}
		}

		/*for (int i=0; i<_iMaxSize; i++,n++)
		{
		if (!n->active)
		{
		n->active = true;
		n->o = o;
		_iSize++;		
		return (i);
		}
		}*/


		return (-1);
	}

	int	Add(OB *o,const char* pcName)
	{
		int iValue_ = 0;
		if(!pcName)
		{
			return IWA_NULL;
		}

		KeyString str_;
		str_ = pcName;

		if(_oObjList.find(str_)!=_oObjList.end())
		{

			return IWA_NULL;
		}

		if((iValue_=Add(o))==IWA_NULL)
		{

			return IWA_NULL;
		}

		WOBJECT_PAIR p1;
		p1.first = str_;
		p1.second = iValue_;
		_oObjList.insert(p1);

		return (iValue_);
	}

	void Remove(const char* pcName)
	{
		if(!pcName)
		{
			return;
		}
		int iValue_ = 0;

		WOBJECT_LIST::iterator iter_;
		iter_ = _oObjList.find(pcName);
		if(iter_!=_oObjList.end())
		{
			iValue_ = _oObjList[pcName];
			Remove(iValue_);
			//_oObjList.erase(iter_);
		}
	}

	void Remove(int h,bool bClearKey=true)
	{
		if (h>=0 && h<_iMaxSize)
		{
			WIDE_OBJECT_NODE *n = &_object[h];
			if (n->active)
			{
				if (n->o) delete n->o;
				n->o = NULL;

				n->active = false;

				if(bClearKey)
				{
					WOBJECT_LIST::iterator iter_;
					iter_ = _oObjList.begin();
					for(;iter_!=_oObjList.end();iter_++)
					{
						if(iter_->second==h)
						{
							_oObjList.erase(iter_);
							break;
						}						
					}
				}

				_iSize--;

				_oFreeList.push(h);
			}
		}
	}

	OB* GetObjectByName(const char* pcName)
	{
		if(!pcName)
		{
			return NULL;
		}

		int iValue_ = 0;

		WOBJECT_LIST::iterator iter_;
		iter_ = _oObjList.find(pcName);
		if(iter_==_oObjList.end())
		{
			return NULL;
		}

		iValue_ = iter_->second;

		if(iValue_>=_iMaxSize||iValue_<0)
		{

			return NULL;
		}

		return _object[iValue_].o;
	}

	OB* GetObjectByID(int iID)
	{

		if(iID>=_iMaxSize||iID<0)
		{

			return NULL;
		}
		if(_object[iID].active!=1)
			return NULL;

		return _object[iID].o;
	}

	OB* ToHeadPtr()
	{

		_iNowPtr = 0;
		for(int i=0;i<_iMaxSize;i++)
		{
			WIDE_OBJECT_NODE *n = &_object[i];
			if (n->active)
			{
				_iNowPtr = i;
				return (n->o);

			}
		}	

		return NULL;
	}

	OB* ToNextPtr()
	{

		for(int i=_iNowPtr+1;i<_iMaxSize;i++)
		{
			WIDE_OBJECT_NODE *n = &_object[i];
			if (n->active)
			{
				_iNowPtr = i;
				return (n->o);

			}
		}	

		return NULL;
	}

	int GetNowID()
	{
		return _iNowPtr;
	}

	void Clear()
	{
		//WIDE_OBJECT_NODE *n = _object;
		//for (int i=0; i<_iMaxSize; i++,n++)
		//{
		//	if (n->active)
		//	{
		//		//OB *o = n->o;
		//		//if(o) delete o;
		//		//n->o = NULL;
		//		n->o.reset();
		//		n->active = false;
		//	}
		//}
		
		//_oObjList.clear();
		//_iSize = 0;
		Reserve(_iMaxSize);
	}

	int GetSize()
	{
		return _iSize;
	}

	OB* operator [](int iPos)
	{
		int iCount_ = 0;
		for(int i=0;i<_iMaxSize;i++)
		{
			if(_object[i].active)
			{
				if(iCount_==iPos)
					return (_object[i].o);
				else
					iCount_++;
			}
		}
		return NULL;
	}

	int FindIDByName(const char* pcName)
	{
		if(!pcName)
			return IWA_NULL;


		WOBJECT_LIST::iterator iter_;
		iter_ = _oObjList.find(pcName);
		if(iter_==_oObjList.end())
		{
			return IWA_NULL;
		}

		int iValue_ = iter_->second;

		if(iValue_>=_iMaxSize||iValue_<0)
		{

			return IWA_NULL;
		}
		return iValue_;
	}

private:
	int _iSize;
	int _iMaxSize;
	WOBJECT_LIST _oObjList;
	WIDE_OBJECT_NODE* _object;
	int _iNowPtr;
	std::queue<int> _oFreeList;
};

}	//	namespace wild
#endif	//	__WILDARRAY_H__
